use std::rc::Rc;
use chrono::{Local};
use crate::business::websocket::dto::im_message_dto::MessageObject;
use crate::db::pojo::pojo::{ImGroup, ImGroupUser, ImMessage, ImMessageActionStatus, ImMessageFileStatus, ImMessageSend, ImMessageStatus, ImSession, ImSessionStatus, ImSessionType, ImSetting, ImUser, MessageType};
use crate::util::const_var::MESSAGE_SPIT;
use crate::util::time::format_time_by_format;

impl ImSession {
    pub fn new(login_user_id: String, message: String, to_user: Option<Rc<ImUser>>, to_group: Option<Rc<ImGroup>>) -> ImSession {
        let to_user_id = if let Some(user) = to_user.clone() {
            Some(user.user_id.clone())
        } else {
            None
        };
        let to_group_code = if let Some(group) = to_group.clone() {
            Some(group.code.clone())
        } else {
            None
        };

        ImSession {
            id: None,
            current_user_id: login_user_id.clone(),
            name: message,
            from_user_id: login_user_id,
            to_user_id,
            server_id: None,
            session_type: ImSessionType::Chat,
            group_code: to_group_code,
            hot_message_total: 0,
            lately_message: "".to_string(),
            is_waking: false,
            is_top: false,
            is_disturb: false,
            is_waking2: false,
            is_top2: false,
            is_disturb2: false,
            ext1: None,
            ext2: None,
            status: ImSessionStatus::Created,
            create_time: Local::now(),
            update_time: Local::now(),

            to_user,
            group: to_group,
        }
    }

    pub fn set_user_id(&mut self, user_id: String) {
        self.current_user_id = user_id.clone();
        self.from_user_id = user_id;
    }

    pub fn build_by_user(user_id: String, to_user: Rc<ImUser>) -> ImSession {
        ImSession {
            id: None,
            current_user_id: user_id.clone(),
            name: to_user.user_name.clone(),
            from_user_id: user_id.clone(),
            to_user_id: Some(to_user.user_id.clone()),
            server_id: None,
            session_type: ImSessionType::Chat,
            group_code: None,
            hot_message_total: 0,
            lately_message: "".to_string(),
            is_waking: false,
            is_top: false,
            is_disturb: false,
            is_waking2: false,
            is_top2: false,
            is_disturb2: false,
            ext1: None,
            ext2: None,
            status: ImSessionStatus::Created,
            create_time: Local::now(),
            update_time: Local::now(),
            to_user: Some(to_user),
            group: None,
        }
    }

    pub fn build_by_group(user_id: String, group: Rc<ImGroup>) -> ImSession {
        ImSession {
            id: None,
            current_user_id: user_id.clone(),
            name: group.name.clone().unwrap(),
            from_user_id: user_id.clone(),
            to_user_id: None,
            server_id: None,
            session_type: ImSessionType::Chat,
            group_code: Some(group.code.clone()),
            hot_message_total: 0,
            lately_message: "".to_string(),
            is_waking: false,
            is_top: false,
            is_disturb: false,
            is_waking2: false,
            is_top2: false,
            is_disturb2: false,
            ext1: None,
            ext2: None,
            status: ImSessionStatus::Created,
            create_time: Local::now(),
            update_time: Local::now(),
            to_user: None,
            group: Some(group),
        }
    }
}

impl ImSetting {
    pub fn new(current_user_id: String, name: String) -> ImSetting {
        ImSetting {
            id: None,
            name,
            current_user_id,
            description: None,
            value: format_time_by_format(&Local::now(), "%Y-%m-%d %H:%M"),
            ext1: None,
            ext2: None,
            create_time: Local::now(),
            update_time: Local::now(),
        }
    }
}

impl ImMessage {

    pub fn is_p2p(&self) -> bool {
        self.to_user_id.is_none()
    }

    pub fn is_sender(&self, user_id: &str) -> bool {
        &self.from_user_id == user_id
    }

    pub fn from(user_id: String, session: Option<ImSession>, message_object: MessageObject) -> ImMessage {
        let local_seq = message_object.local_seq;
        let server_id = if local_seq.contains(MESSAGE_SPIT) {
            local_seq.split(MESSAGE_SPIT).collect::<Vec<&str>>()[0].to_owned()
        } else {
            local_seq
        };
        let session_id = match session {
            None => {0}
            Some(session) => { session.id.clone().unwrap()}
        };
        ImMessage {
            id: None,
            client_id: message_object.server_id.clone().unwrap(),
            current_user_id: user_id.clone(),
            from_user_id: message_object.from_user_id,
            to_user_id: message_object.to_user_id,
            server_id: Some(server_id),
            message_type: message_object.message_type,
            group_code: message_object.group_code,
            content: message_object.content,
            session_id,
            ref_type: None,
            ref_message_ids: None,
            ext: None,
            ext1: None,
            ext2: None,
            version: 1,
            status: ImMessageStatus::wrap(true, &message_object.status),
            file_status: ImMessageFileStatus::None,
            action_status: ImMessageActionStatus::None,
            server_receive_time: None,
            create_date_time: Local::now(),
            update_date_time: Local::now(),
            message_send_set: None,
            
            session: None,
        }
    }
}

impl ImMessageSend {
    pub fn new(user_id: String) -> ImMessageSend {
        ImMessageSend {
            id: None,
            message_id: None,
            user_id,
            status: ImMessageStatus::Created,
            file_status: ImMessageFileStatus::None,
            action_status: ImMessageActionStatus::None,
            create_time: Local::now(),
            update_time: Local::now(),
        }
    }
}

impl From<&ImGroupUser> for ImMessageSend {
    fn from(value: &ImGroupUser) -> Self {
        ImMessageSend::new(value.user_id.clone())
    }
}

impl From<&str> for MessageType {
    fn from(value: &str) -> Self {
        log::info!("message type: {}", value);
        match value {
            "Text" => MessageType::Text,
            "Image" => MessageType::Image,
            "Web" => MessageType::Web,
            "File" => MessageType::File,
            "Html" => MessageType::Html,
            "Video" => MessageType::Video,
            "RichText" => MessageType::RichText,
            "Audio" => MessageType::Audio,
            "Url" => MessageType::Url,
            "Group" => MessageType::Group,
            "Chat"=> MessageType::Chat,
            _ => MessageType::Text,
        }
    }
}
